package com.lzf.config;

import com.lzf.filter.CheckClientParameterFilter;
import com.lzf.filter.CustomClientCredentialsTokenEndpointFilter;
import com.lzf.handler.MyAuthenticationEntryPoint;
import com.lzf.handler.MyExceptionTranslator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.sql.DataSource;


@Configuration
@EnableAuthorizationServer
public class AuthConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;
    @Autowired
    private MyExceptionTranslator myExceptionTranslator;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()")// /oauth/token_key
                .checkTokenAccess("permitAll()")// /oauth/check_token
                //.allowFormAuthenticationForClients()
        ;
        //参数检查, (authenticationManager 是否可以自定义认证管理器)
        CheckClientParameterFilter checkBodyParameterFilter = new CheckClientParameterFilter(authenticationManager,myAuthenticationEntryPoint);
        security.addTokenEndpointAuthenticationFilter(checkBodyParameterFilter);

        //自定义client_id或client_secret错误
        CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security);
        endpointFilter.afterPropertiesSet();
        endpointFilter.setAuthenticationEntryPoint(myAuthenticationEntryPoint);
        // 客户端认证之前的过滤器，覆盖默认 AuthenticationEntryPoint，使用自定义 myAuthenticationEntryPoint
        security.addTokenEndpointAuthenticationFilter(endpointFilter);


    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
        jdbcClientDetailsService.setPasswordEncoder(passwordEncoder);
        clients.withClientDetails(jdbcClientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                //授权码模式
                .authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource))
                .tokenServices(tokenServices())
                //使用默认TokenEndpoint接口获取token
                .allowedTokenEndpointRequestMethods(HttpMethod.POST)
                //自定义MyExceptionTranslator
                .exceptionTranslator(myExceptionTranslator);
    }



    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setClientDetailsService(clientDetailsService);
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setTokenStore(tokenStore);
        return defaultTokenServices;
    }
}
